//【工具函数】/【网络通信】/【微信小程序请求封装类】

export default class WxRequest {
  // 默认配置参数
  private _defaultOptions: WxRequestDefaultOption = {
    timeout: 10000,
  }

  // 请求方法快捷方式
  get: (url: string, data?: any, options?: WxRequestOption) => Promise<any> = this._genQuickMethod('GET')
  post: (url: string, data?: any, options?: WxRequestOption) => Promise<any> = this._genQuickMethod('POST')
  put: (url: string, data?: any, options?: WxRequestOption) => Promise<any> = this._genQuickMethod('PUT')
  delete: (url: string, data?: any, options?: WxRequestOption) => Promise<any> = this._genQuickMethod('DELETE')


  // 拦截器
  interceptors = {
    // 请求拦截器，在请求发送之前，对请求参数进行处理
    request: (options: WxRequestOption) => options,

    // 响应拦截器，在请求成功后，对响应数据进行处理
    response: (response: WechatMiniprogram.RequestSuccessCallbackResult<WxResponse>) => response,

    // 请求失败拦截器，在请求失败后，对错误信息进行处理
    fail: (error: WechatMiniprogram.RequestFailCallbackErr)
      : WechatMiniprogram.RequestFailCallbackErr | string | null => error,
  }


  // 构造函数，初始化默认配置参数
  constructor(defaultOptions?: WxRequestDefaultOption) {
    Object.assign(this._defaultOptions, defaultOptions)
  }


  // 请求方法，返回 Promise
  request(options: WechatMiniprogram.RequestOption) {
    // 存储拦截器
    const interceptors = this.interceptors

    // 调用请求拦截器
    options = interceptors.request(options)

    // 返回 Promise
    return new Promise((resolve, reject) => {
      wx.request({
        ...options,

        // 用户可定义的请求参数
        url: this._defaultOptions.baseUrl + options.url,
        timeout: this._defaultOptions.timeout,

        // 请求成功
        success(res: WechatMiniprogram.RequestSuccessCallbackResult<WxResponse>) {
          // 调用响应拦截器
          res = interceptors.response(res)
          resolve(res)
        },

        // 请求失败
        fail(err) {
          // 调用请求失败拦截器
          const errorResult = interceptors.fail(err)

          // 如果请求失败拦截器返回 null，则不执行 reject
          if (errorResult) reject(errorResult)
        },
      })
    })
  }


  // 请求快捷方法构建函数
  private _genQuickMethod(method: WxRequestMethod) {
    return (url: string, data?: any, options?: WxRequestOption) => {
      return this.request({...options, url, method, data})
    }
  }
}
